/**
 * 
 */
package com.baijia.tianxiao.push.biz.channel.imp;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.baidu.yun.core.log.YunLogEvent;
import com.baidu.yun.core.log.YunLogHandler;
import com.baidu.yun.push.auth.PushKeyPair;
import com.baidu.yun.push.client.BaiduPushClient;
import com.baidu.yun.push.constants.BaiduPushConstants;
import com.baidu.yun.push.exception.PushClientException;
import com.baidu.yun.push.exception.PushServerException;
import com.baidu.yun.push.model.PushMsgToSingleDeviceRequest;
import com.baidu.yun.push.model.PushMsgToSingleDeviceResponse;
import com.baijia.tianxiao.push.biz.channel.StandardChannel;
import com.baijia.tianxiao.push.biz.channel.StandardChannelUtils;
import com.baijia.tianxiao.push.enums.ChannelTypeEnum;
import com.baijia.tianxiao.push.enums.DeviceTypeEnum;
import com.baijia.tianxiao.push.enums.PushCodeEnum;
import com.baijia.tianxiao.push.model.PushChannelConfig;
import com.baijia.tianxiao.push.result.BasePushResult;
import com.baijia.tianxiao.push.service.PushChannelConfigService;

/**
 * @author leiruiqi
 *
 */

@Component
public class BaiduPushChannelImpl implements StandardChannel{
	
	private static Logger logger = LoggerFactory.getLogger(BaiduPushChannelImpl.class); 
	
	//BaiduPushClient pushClient;
	
	private Map<String,BaiduPushClient> pushClientMap;
	
	@Resource
	private PushChannelConfigService pushChannelConfigService;
	
	
	@PostConstruct
	public void init(){
		// 1. get apiKey and secretKey from developer console
		//String apiKey = "i30C5KZPV4eUNgsl15mQ4Gyh";
		//String secretKey = "zqNmmO7ywrADSdD7GeBwlFU6zpysvq4k";
		//PushKeyPair pair = new PushKeyPair(apiKey, secretKey);

		// 2. build a BaidupushClient object to access released interfaces
		//pushClient = new BaiduPushClient(pair,
		//		BaiduPushConstants.CHANNEL_REST_URL);

		// 3. register a YunLogHandler to get detail interacting information
		// in this request.
		pushClientMap = new HashMap<String,BaiduPushClient>();
		
		// 放进统一的ChannelMap中
		
		StandardChannel.channelMap.put(ChannelTypeEnum.BAIDU.name(), this);
	}
	
	private BaiduPushClient getClient(DeviceTypeEnum deviceType,String appId,Integer developStatus){
		String key = StandardChannelUtils.buildClientKey(deviceType, appId, developStatus);
		BaiduPushClient client =  pushClientMap.get(key);
		if(client == null){
			PushChannelConfig channelApp = pushChannelConfigService.getByChannelTypeAndIdByCache(ChannelTypeEnum.BAIDU.name(),deviceType, appId,developStatus);
			if(channelApp != null){
				PushKeyPair pair = new PushKeyPair(channelApp.getAppKey(), channelApp.getAppSecret());

				client = new BaiduPushClient(pair,
						BaiduPushConstants.CHANNEL_REST_URL);

				client.setChannelLogHandler(new YunLogHandler() {
					@Override
					public void onHandle(YunLogEvent event) {
						doExcuteEvent(event);
					}
				});
				
				pushClientMap.put(key, client);
			}
			
		}
		
		return client;
	}
	private void doExcuteEvent(YunLogEvent event){
		logger.info("YunLogEvent "+event.getMessage(),event);
	}

	public BasePushResult sendPushMsg(JSONObject messageInfo, String appId,String deviceToken,String deviceType,Integer developStatus,Integer deployStatus) {
		
		DeviceTypeEnum typeEnum = DeviceTypeEnum.getByName(deviceType);
		if(typeEnum == null){
			return new BasePushResult(false, "deviceType not suport");	
		}
		
		BaiduPushClient pushClient = getClient(typeEnum,appId,developStatus);
		
		if(pushClient == null){
			return new BasePushResult(false, "appId not config");	
		}
		JSONObject jsono = null;
		
		if(typeEnum == DeviceTypeEnum.ANDROID){
			jsono = buildAndroidNotification(messageInfo);
		}
		else if(typeEnum == DeviceTypeEnum.IOS){
			jsono = buildIOSNotification(messageInfo);
		}
		if(jsono == null){
			return new BasePushResult(false, "deviceType not suport");		
		}
		try {
			PushMsgToSingleDeviceResponse response = this.sendNotification(pushClient,jsono, deviceToken, deployStatus);
			checkSendResult(response);
			return new BasePushResult(true, null);
		} catch (PushClientException e) {
			logger.error("PushClientException",e);
			return new BasePushResult(false, "");
		} catch (PushServerException e) {
			logger.error("PushServerException",e);
			logger.error(String.format(
					"requestId: %d, errorCode: %d, errorMessage: %s",
					e.getRequestId(), e.getErrorCode(), e.getErrorMsg()));
			BasePushResult result = new BasePushResult(false, e.getErrorMsg());
			if(e.getErrorCode() == 30608){
				result.setCode(PushCodeEnum.bind_no_found.name());
			}
			return result;
		}
		
		//
		
	}
	private void checkSendResult(PushMsgToSingleDeviceResponse response){
		
	}
	
	
	
	public JSONObject buildAndroidNotification(JSONObject pushMessage){
		JSONObject notification = new JSONObject();
		
		notification.put("description",pushMessage.get("description"));
		
		JSONObject jsonCustormCont = new JSONObject();
		jsonCustormCont.put("t", "1"); //消息类型 0:默认系统消息，1:IM消息,2:问答消息 3:找老师消息
		jsonCustormCont.put("f", "b"); //消息来源，b:百度
		jsonCustormCont.put("cc", "xxx"); //回调码
		jsonCustormCont.put("s",pushMessage.get("s"));   //schema跳转
		
		JSONObject notify = new JSONObject();
		notify.put("sound", "0");
		notify.put("shake", "0");
		notify.put("notice", "0");
		jsonCustormCont.put("notification", notify);
		
		notification.put("custom_content", jsonCustormCont);
		
		return notification;
	}

	public JSONObject buildIOSNotification(JSONObject pushMessage){
		
		JSONObject notification = new JSONObject();
		JSONObject jsonAPS = new JSONObject();
		jsonAPS.put("alert", pushMessage.get("description"));
		jsonAPS.put("sound", "default"); // 设置通知铃声样式，例如"ttt"，用户自定义。
		notification.put("aps", jsonAPS);
				
		notification.put("t", "1"); //消息类型 0:默认系统消息，1:IM消息,2:问答消息 3:找老师消息
		notification.put("f", "b"); //消息来源，b:百度
		notification.put("cc", "xxx"); //回调码
		notification.put("s",pushMessage.get("s"));   //schema跳转
		
		return notification;
	}
	
	public PushMsgToSingleDeviceResponse sendNotification(BaiduPushClient pushClient,JSONObject notification,String deviceToken,Integer status)throws PushClientException,
	PushServerException {
		
		PushMsgToSingleDeviceRequest request = new PushMsgToSingleDeviceRequest()
				.addChannelId(deviceToken)
				.addMsgExpires(new Integer(3600)). // 设置message的有效时间
				
				addMessage(notification.toString());
			
			if(status == null){
				request.addMessageType(0);// 1：通知,0:透传消息.默认为0 注：IOS只有通知.
				request.addDeviceType(3);
				
			}
			else if(status<=2){
				request.addMessageType(1);// 1：通知,0:透传消息.默认为0 注：IOS只有通知.
				request.addDeployStatus(status). // IOS,
				// DeployStatus
				// => 1: Developer
				// 2: Production.
				addDeviceType(4);// deviceType => 3:android, 4:ios
			}
			
		//logger.info("baidu send request info="+request.toString());
			PushMsgToSingleDeviceResponse response = null;
		try {
			response = pushClient
					.pushMsgToSingleDevice(request);
			// Http请求结果解析打印
			logger.info("msgId: " + response.getMsgId() + ",sendTime: "
					+ response.getSendTime());
			return response;
		} catch (PushClientException e) {
			/*
			 * ERROROPTTYPE 用于设置异常的处理方式 -- 抛出异常和捕获异常,'true' 表示抛出, 'false' 表示捕获。
			 */
			/*if (BaiduPushConstants.ERROROPTTYPE) {
				throw e;
			} else {
				e.printStackTrace();
			}*/
			throw e;
		} catch (PushServerException e) {
			/*if (BaiduPushConstants.ERROROPTTYPE) {
				throw e;
			} else {
				logger.error(String.format(
						"requestId: %d, errorCode: %d, errorMessage: %s",
						e.getRequestId(), e.getErrorCode(), e.getErrorMsg()));
			}*/
			throw e;
		}
		/*finally{
			return response; 
		}*/
			
	}

	@Override
	public void nofifyChannelConfigChange() {
		pushClientMap.clear();
		logger.info("baidu channel clear pushClientMap end");
	}
	
	/*public static void main(String[] args) {
		BaiduPushChannel channel = new BaiduPushChannel();
		channel.init();
		PushBindRecord record = new PushBindRecord();
		record.setUserId("123-123");
		record.setUserType("tx");
		record.setDeviceDomain(DeviceDomainEnum.MOBILE.name());
		record.setDeviceType(DeviceTypeEnum.ANDROID.name());
		channel.sendPushMsg(messageInfo, record., deviceType, status)
	}*/
}